import { tuple, truthy } from '@gnlab/utils'
import { makeHTTPSAvatar } from '@/lib/https'
import {
  type ContactMeta,
  type RawContactMeta,
  formatRawContactMeta,
} from '@/services/contact-chat'
import type {
  ExternalContact,
  InternalContact,
  GroupContact,
  NoticeContact,
  TransferedExternal,
} from '@/services/contact-types/'

export { type ContactMeta, type RawContactMeta, formatRawContactMeta }

/**
 * 定义联系人类型
 */
export enum ContactType {
  external = 'external', // 客户
  internal = 'internal', // 员工
  group = 'group', // 群
  notice = 'notice', // 应用通知
}

export const contactTypeMap: { [type in ContactType]: string } = {
  [ContactType.external]: '客户',
  [ContactType.internal]: '员工',
  [ContactType.group]: '群',
  [ContactType.notice]: '通知',
}

export type Contact = ExternalContact | InternalContact | GroupContact | NoticeContact
export type ContactWithTransfer = Contact | TransferedExternal

/**
 * 最基本的联系人信息
 */
export interface BasicContact {
  id: string // 由 makeContactId() 基于联系人信息生成的唯一 id
  conversationId: string // 向此联系人发送消息时要用到的“会话ID”
  ownerWxid: string // 联系人归属的企业微信 id
  userId: string // 联系人的用户 id，对于“群”和“通知”，等同于 conversationId
  avatar: string // 联系人头像
  name: string // 联系人名称
  remark: string // 备注名，有此信息的情况下将此值作为优先显示的“名称”
}

// hook 端返回的原始联系人信息
export interface HookContact {
  avatar: string
  conversation_id: string
  corp_id: string
  nickname?: string
  position: string
  realname: string
  remark: string
  sex: 1 | 2 // 1 男   2 女
  user_id: string
  username: string
}

type BasicHookContact = Omit<HookContact, 'corp_id' | 'position' | 'sex'>
export function formatBasicHookContact(ownerWxid: string, raw: BasicHookContact): BasicContact {
  const id = makeContactId(ownerWxid, raw.user_id)
  return {
    avatar: makeHTTPSAvatar(raw.avatar),
    conversationId: raw.conversation_id,
    id,
    name: raw.username || (raw.nickname ?? '') || raw.realname,
    ownerWxid,
    remark: raw.remark || '',
    userId: raw.user_id,
  }
}

/**
 * 各类联系人基于的基本类型
 */
export type BaseContact = BasicContact & ContactMeta
export type RawBaseContact = HookContact & RawContactMeta

type BasicRawBaseContact = BasicHookContact & RawContactMeta
export function formatRawBaseContact(ownerWxid: string, raw: BasicRawBaseContact): BaseContact {
  return {
    ...formatBasicHookContact(ownerWxid, raw),
    ...formatRawContactMeta(ownerWxid, raw),
  }
}

// ============================================================

/**
 * 返回与企业微信返回值同一格式的时间戳（单位是“秒”）
 */
export function getTimestamp() {
  return Math.floor(new Date().getTime() / 1000)
}

/**
 * 生成此 app 自定标准的 contactId
 */
export function makeContactId(ownerWxid: string, contactUserId: string) {
  return `${ownerWxid}-${contactUserId}`
}

/**
 * 拆分由 makeContactId() 生成的 contactId，返回 [ownerWxid, contactUserId]
 */
export function splitContactId(contactId: string) {
  return contactId.split('-', 2) as [string, string]
}

/**
 * 基于联系人信息拼出 conversation_id
 */
export function makeConversationId(base: {
  type: ContactType | null // 明确知道不是群或通知时，可传 null
  ownerWxid: string
  contactUserId: string
}) {
  const { type, ownerWxid, contactUserId } = base
  if (type === ContactType.group || type === ContactType.notice) return contactUserId
  return `S:${(ownerWxid < contactUserId
    ? [ownerWxid, contactUserId]
    : [contactUserId, ownerWxid]
  ).join('_')}`
}

/**
 * 从 conversationId 中提取出联系人的 userId
 * 若联系人不是普通联系人，返回 null
 */
export function getContactUserId(ownerWxid: string, conversationId: string) {
  if (!detectIsNormal(conversationId)) return null
  if (detectIsGroup(conversationId) || detectIsNotice(conversationId)) return conversationId
  const split = splitPeopleConversationId(conversationId)
  return split[0] === ownerWxid ? split[1] : split[0]
}

/**
 * 基于 conversationId 生成 contactId
 * 若联系人不是普通联系人，返回 null
 */
export function makeContactIdByConversationId(ownerWxid: string, conversationId: string) {
  const contactUserId = getContactUserId(ownerWxid, conversationId)
  return truthy(contactUserId) ? makeContactId(ownerWxid, contactUserId) : null
}

/**
 * 判断指定 conversation_id 是否属于一个标准的联系人（例如不是系统提醒之类的）
 * 注意：应用提醒（O:123123123）和群联系人（R:12312312321）被视为是标准联系人
 */
export function detectIsNormal(conversationId: string) {
  if (conversationId.startsWith('Y:')) return false // 系统提醒
  return true
}

/**
 * 判断一个 conversation_id 是不是“群”
 */
export function detectIsGroup(conversationId: string) {
  return conversationId.startsWith('R:')
}

/**
 * 判断一个 conversation_id 是不是“应用提醒”
 */
export function detectIsNotice(conversationId: string) {
  return conversationId.startsWith('O:')
}

/**
 * 判断一个 conversation_id 是不是“企业微信”联系人
 * 注意：企业微信联系人，有可能是内部员工联系人，也可能是“企业微信”类型的外部联系人
 */
export function detectIsQywxContact(conversationId: string) {
  if (!conversationId.startsWith('S:')) return false
  const [id1, id2] = conversationId.slice(2).split('_') as [string, string]
  return isQywxWxid(id1) && isQywxWxid(id2)
}

/**
 * 判断一个 conversation_id 是否属于“自然人”（即“客户”或“员工”）
 */
export function detectIsPersonContact(conversationId: string) {
  return conversationId.startsWith('S:')
}

/**
 * 判断一个 wxid 是否是企业微信的
 */
export function isQywxWxid(wxid: string) {
  return wxid.startsWith('168')
}

/**
 * 判断一个 wxid 是否是企业微信群机器人
 */
export function isGroupRobot(wxid: string) {
  return wxid.startsWith('10')
}

/**
 * 判断一个 wxid 是否是个人微信的
 * （除了企业微信和个人微信的 wxid，群里还有可能出现 10 开头的机器人 wxid）
 */
export function isWechatWxid(wxid: string) {
  return wxid.startsWith('78')
}

/**
 * 提取自然人（客户、员工）的 conversation_id 里的两个 wxid
 * 需事先确认好是这两种联系人的 conversation_id，否则会返回两个空字符串
 */
export function splitPeopleConversationId(conversationId: string) {
  if (!detectIsPersonContact(conversationId)) return tuple('', '')
  const [id1, id2] = conversationId.slice(2).split('_')
  return tuple(id1!, id2!)
}

/**
 * 用于联系人排序的比较函数
 */
export function compareContacts<T extends Contact>(a: T, b: T) {
  return b.contacted - a.contacted
}
